﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MasterDetailTemplate.Models;

namespace MasterDetailTemplate.Services.Implementations
{
    /// <summary>
    /// 同步服务。
    /// </summary>
    public class SyncService : ISyncService
    {
        /// <summary>
        /// 偏好存储。
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        /// <summary>
        /// 本地事件存储。
        /// </summary>
        private IEventStorage _localEventStorage;

        /// <summary>
        /// 远程事件存储。
        /// </summary>
        private IRemoteEventStorage _remoteEventStorage;

        /// <summary>
        /// 状态。
        /// </summary>
        public string Status
        {
            get => _status;
            private set
            {
                _status = value;
                StatusChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 状态。
        /// </summary>
        private string _status;

        /// <summary>
        /// 状态改变事件。
        /// </summary>
        public event EventHandler StatusChanged;

        /// <summary>
        /// 偏好存储的键。
        /// </summary>
        public static string Last_Sync = "lastSyncDateStamp";

        /// <summary>
        /// 同步。
        /// </summary>
        public async Task SyncAsync()
        {
            if (_preferenceStorage.Get(Last_Sync, long.MinValue) ==
                long.MinValue)
            {
                //说明本地还没同步过，就给它设置成最小时间
                _preferenceStorage.Set(Last_Sync,long.MinValue);
            }


            var lastSyncTime = _preferenceStorage.Get(Last_Sync, long.MinValue);

            //开始进行同步操作
            //1.读取本地所有事件。
            var localList = await _localEventStorage.GetAllEventsAsync();

            //2.读取远程收藏项
            Status = "正在读取远程日期事件项";
            var remoteList = await _remoteEventStorage.GetEventsAsync();

            Dictionary<long, Event> localDictionary =
                new Dictionary<long, Event>();
            Dictionary<long, Event> remoteDictionary =
                new Dictionary<long, Event>();

            await Task.Run(() => {
                //3.俩个列表进行统一
                localDictionary = localList.ToDictionary(e => e.Id, e => e);
                remoteDictionary = remoteList.ToDictionary(e => e.Id, e => e);
                var localDictionaryKeyList = localDictionary.Keys.ToList();
                //先遍历本地
                foreach (var localEventKey in localDictionaryKeyList)
                {
                    var localEvent = localDictionary[localEventKey];
                    if (remoteDictionary.TryGetValue(localEventKey,
                        out var remoteEvent))
                    {
                        //事件对象在两个字典中均存在。
                        if (remoteEvent.DateStamp > localEvent.DateStamp)
                        {
                            //远程是最新的。
                            localDictionary[localEventKey] = remoteEvent;
                        }
                        else if (remoteEvent.DateStamp <
                          localEvent.DateStamp)
                        {
                            //本地是最新的
                            remoteDictionary[remoteEvent.Id] = localEvent;
                        }
                    }
                    else
                    {
                        //事件对象在本地存在，在远程不存在。
                        if (localEvent.DateStamp < lastSyncTime)
                        {
                            //时间戳小于上一次本地同步的时间，删除
                            localDictionary.Remove(localEventKey);
                            
                        }
                        else if (localEvent.DateStamp > lastSyncTime)
                        {
                            remoteDictionary.Add(localEventKey, localEvent);
                        }
                    }
                }

                _localEventStorage.DeleteAllEvent();    
                /*
                 * 本地遍历一遍过后，远程字典中就变成了本地的字典+远程多的id
                 * 因此只需要找本地没有的进行操作就ok了
                 */
                var remoteDictionaryKeyList = remoteDictionary.Keys.ToList();
                foreach (var remoteEventkey in remoteDictionaryKeyList)
                {
                    var remoteEvent = remoteDictionary[remoteEventkey];
                    if (!localDictionary.ContainsKey(remoteEventkey))
                    {
                        if (remoteEvent.DateStamp > lastSyncTime)
                        {
                            localDictionary[remoteEvent.Id] = remoteEvent;
                        }
                        else if (remoteEvent.DateStamp < lastSyncTime)
                        {
                            remoteDictionary.Remove(remoteEvent.Id);
                        }
                    }
                }
            });

            //保存数据
            foreach (var localEvent in localDictionary.Values)
            {
                
                await _localEventStorage.SaveEventAsync(localEvent);
            }

            Status = "正在保存远程收藏项";
            await _remoteEventStorage.SaveEventsAsync(remoteDictionary.Values
                .ToList());

            await Task.Delay(1000);
            //同步结束，设置成刚刚同步的日期
            _preferenceStorage.Set(Last_Sync, DateTime.Now.Ticks);
        }

        /// <summary>
        /// 同步服务。
        /// </summary>
        /// <param name="localEventStorage">本地收藏存储。</param>
        /// <param name="remoteEventStorage">远程收藏存储。</param>
        /// <param name="preferenceStorage">偏好存储。</param>
        public SyncService(IEventStorage localEventStorage,
            IRemoteEventStorage remoteEventStorage,
            IPreferenceStorage preferenceStorage)
        {
            _localEventStorage = localEventStorage;
            _remoteEventStorage = remoteEventStorage;
            _preferenceStorage = preferenceStorage;
        }
    }
}
